﻿using System;
using System.IO;
using System.Security.Cryptography;
using System.Text;
using Taxhui.Utils.IOUtils;

namespace Taxhui.Utils.CryptUtils
{
    public static class DESCrypt
    {
        #region 转换
        private static byte[] GetKeyByte(string key, int v, Encoding sEncode)
        {
            return DataUtil.GetKeyByte(key, v, sEncode);
        }

        private static string ByteToStr(byte[] passByte)
        {
            return DataUtil.ByteToStr(passByte);
        }
        private static bool CheckData(byte[] org, ref Encoding sEncode)
        {
            return DataUtil.CheckData(org,ref sEncode);
        }

        private static byte[] StrToByte(string pass)
        {
            return DataUtil.StrToByte(pass);
        }
        #endregion
        #region DES加密解密
        /// <summary>
        /// DES加密
        /// </summary>
        /// <param name="txt">原文</param>
        /// <param name="key">密码</param>
        /// <param name="keyIV">偏移</param>
        /// <param name="sEncode">编码</param>
        /// <returns></returns>
        public static string DESEncrypt(string txt, string key, string keyIV, Encoding sEncode = null, CipherMode mode = CipherMode.CBC, PaddingMode padding = PaddingMode.PKCS7)
        {
            try
            {
                sEncode = sEncode ?? Encoding.UTF8;
                byte[] orgByte = sEncode.GetBytes(txt);//原文
                byte[] passByte = DESEncrypt(orgByte, key, keyIV, sEncode, mode, padding);//加密
                return  ByteToStr(passByte);
            }
            catch (Exception)
            {
                throw;
            }
        }

        

        public static byte[] DESEncrypt(byte[] org, string key, string keyIV, Encoding sEncode = null, CipherMode mode = CipherMode.CBC, PaddingMode padding = PaddingMode.PKCS7)
        {
            if (!CheckData(org, ref sEncode))
                return null;
            byte[] keyByte = GetKeyByte(key, 8, sEncode);
            byte[] keyIVByte = GetKeyByte(keyIV, 8, sEncode);
            if (!string.IsNullOrEmpty(keyIV))
                keyIVByte = sEncode.GetBytes(keyIV);
            return DESEncrypt(org, keyByte, keyIVByte, mode, padding);
        }
        public static byte[] DESEncrypt(byte[] org, byte[] key, byte[] keyIV, CipherMode mode = CipherMode.CBC, PaddingMode padding = PaddingMode.PKCS7)
        {
            DESCryptoServiceProvider des = new DESCryptoServiceProvider
            {
                Key = key,//密钥
                IV = keyIV,//偏移
                Mode = mode,
                Padding = padding
            };
            MemoryStream ms = new MemoryStream();//内存流
            CryptoStream cs = new CryptoStream(ms, des.CreateEncryptor(), CryptoStreamMode.Write);//加解密流
            cs.Write(org, 0, org.Length);//加密
            cs.FlushFinalBlock();
            cs.Close();
            des.Clear();
            des.Dispose();
            return ms.ToArray();
        }

        /// <summary>
        /// DES解密
        /// </summary>
        /// <param name="pass">密文</param>
        /// <param name="key">密码</param>
        /// <param name="keyIV">偏移</param>
        /// <param name="sEncode">编码</param>
        /// <param name="mode">运算模式</param>
        /// <param name="padding">填充模式</param>
        /// <returns></returns>
        public static string DESDecrypt(string pass, string key, string keyIV, Encoding sEncode = null, CipherMode mode = CipherMode.CBC, PaddingMode padding = PaddingMode.PKCS7)
        {
            try
            {
                sEncode = sEncode ?? Encoding.UTF8;
                byte[] orgByte = StrToByte(pass);
                byte[] retByte = DESDecrypt(orgByte, key, keyIV, sEncode, mode, padding);
                return sEncode.GetString(retByte);
            }
            catch (Exception)
            {
                throw;
            }
        }


        public static byte[] DESDecrypt(byte[] passByte, string key, string keyIV, Encoding sEncode = null, CipherMode mode = CipherMode.CBC, PaddingMode padding = PaddingMode.PKCS7)
        {
            if (!CheckData(passByte, ref sEncode))
                return null;
            byte[] keyByte = GetKeyByte(key, 8, sEncode);
            byte[] keyIVByte = GetKeyByte(keyIV, 8, sEncode);
            return DESDecrypt(passByte, keyByte, keyIVByte, mode, padding);
        }
        public static byte[] DESDecrypt(byte[] passByte, byte[] key, byte[] keyIV, CipherMode mode = CipherMode.CBC, PaddingMode padding = PaddingMode.PKCS7)
        {
            DESCryptoServiceProvider des = new DESCryptoServiceProvider
            {
                Key = key,
                IV = keyIV,
                Padding = padding,
                Mode = mode
            };
            MemoryStream ms = new MemoryStream();
            CryptoStream cs = new CryptoStream(ms, des.CreateDecryptor(), CryptoStreamMode.Write);
            cs.Write(passByte, 0, passByte.Length);
            cs.FlushFinalBlock();
            cs.Close();
            des.Clear();
            des.Dispose();
            return ms.ToArray();
        }
        #endregion
        #region 3DES加密解密
        /// <summary>
        /// 3DES加密
        /// </summary>
        /// <param name="str">要加密的字符串</param>
        /// <param name="key">密钥24位</param>
        /// <param name="keyIV">矢量（CBC模式）</param>
        /// <param name="sEncode">编码，默认UTF8</param>
        /// <param name="mode">运算模式</param>
        /// <param name="padding">填充模式</param>
        /// <returns></returns>
        public static string Encrypt3Des(string str, string key, string keyIV, Encoding sEncode = null, CipherMode mode = CipherMode.ECB, PaddingMode padding = PaddingMode.PKCS7)
        {
            if (string.IsNullOrEmpty(str))
                return null;
            sEncode = sEncode ?? Encoding.UTF8;
            byte[] data = sEncode.GetBytes(str);
            return ByteToStr(Encrypt3Des(data, key, keyIV, sEncode, mode, padding));
        }
        public static byte[] Encrypt3Des(byte[] data, string key, string keyIV, Encoding sEncode = null, CipherMode mode = CipherMode.ECB, PaddingMode padding = PaddingMode.PKCS7)
        {
            if (!CheckData(data, ref sEncode))
                return null;
            byte[] keyByte = GetKeyByte(key, 24, sEncode);
            byte[] keyIVByte = GetKeyByte(keyIV, 24, sEncode);
            return Encrypt3Des(data, keyByte, keyIVByte,  mode, padding);
        }
        public static byte[] Encrypt3Des(byte[] data, byte[] key, byte[] keyIV, CipherMode mode = CipherMode.ECB, PaddingMode padding = PaddingMode.PKCS7)
        {
            TripleDESCryptoServiceProvider des = new TripleDESCryptoServiceProvider
            {
                Key = key,
                IV = keyIV,
                Mode = mode,
                Padding = padding
            };
            var encryptor = des.CreateEncryptor();
            byte[] buff = encryptor.TransformFinalBlock(data, 0, data.Length);
            encryptor.Dispose();
            des.Clear();
            des.Dispose();
            return buff;
        }
        /// <summary>
        /// 3DES解密
        /// </summary>
        /// <param name="str">密文</param>
        /// <param name="key">密钥24位</param>
        /// <param name="keyIV">矢量24位，CBC模式有效</param>
        /// <param name="sEncode">编码 默认UTF8</param>
        /// <param name="mode">计算方式</param>
        /// <param name="padding">填充方式</param>
        /// <returns></returns>
        public static string Decrypt3DES(string str,string key,string keyIV,Encoding sEncode=null,CipherMode mode=CipherMode.ECB,PaddingMode padding=PaddingMode.PKCS7)
        {
            if (string.IsNullOrWhiteSpace(str))
                return null;
            sEncode = sEncode ?? Encoding.UTF8;
            byte[] data = StrToByte(str);
            return ByteToStr(Decrypt3DES(data, key, keyIV, sEncode, mode, padding));
        }

        public static byte[] Decrypt3DES(byte[] data,string key,string keyIV,Encoding sEncode=null,CipherMode mode = CipherMode.ECB,PaddingMode padding = PaddingMode.PKCS7)
        {
            if (!CheckData(data,ref sEncode))
                return null;
            byte[] keyByte = GetKeyByte(key, 24, sEncode);
            byte[] keyIVByte = GetKeyByte(keyIV, 24, sEncode);
            return Decrypt3DES(data, keyByte, keyIVByte, mode, padding);
        }
        public static byte[] Decrypt3DES(byte[] data, byte[] key, byte[] keyIV, CipherMode mode = CipherMode.ECB, PaddingMode padding = PaddingMode.PKCS7)
        {            
            
            TripleDESCryptoServiceProvider des = new TripleDESCryptoServiceProvider();            
            des.Key = key;            
            des.Mode = mode;
            des.Padding = padding;
            ICryptoTransform cryptor = des.CreateDecryptor();
            byte[] deData = cryptor.TransformFinalBlock(data, 0, data.Length);
            des.Clear();
            des.Dispose();
            return deData; 
        }
        #endregion
    }
}
